#※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※
# File Name: network.sh
# Author: GID5564
# Description:
# Created Time: 05/07/24-16:43:23
#※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※
#! /usr/bin/env bash

# 避免重复导入
#[[ -n $__XLIB_IMPORTED__NET ]] && return 0
#__XLIB_IMPORTED__NET=1


function __network_init__(){
    wait
}

########################################
# 描述: 判断是否为IPV4地址
# 参数: $1:字符串 
# 返回: 1: 否；
#       0: 是
# 实例: IsIPv4 <addr>
########################################
function IsIPv4() {
    local -r regex='^((25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$'

    [[ $1 =~ $regex ]]
    return $?
}

########################################
# 描述: 判断fqdn是否有效
# 参数: $1:字符串 
# 返回: 1: 无效；
#       0: 有效
# 实例: IsFQDN <fqdn>
########################################
function IsFQDN() {
    echo "$1" | grep -Pq '(?=^.{4,255}$)(^((?!-)[a-zA-Z0-9-]{1,63}(?<!-)\.)+[a-zA-Z]{2,63}\.?$)'

    return $?
}

########################################
# 描述: 测试IPv4十进制网络掩码是否有效
# 参数: $1:掩码
# 返回: 1: 无效；
#       0: 有效
# 实例: Is_IPv4_Netmask <mask>
########################################
function Is_IPv4_Netmask() {
    IsIPv4 "$1" || return 1

    IFS='.' read -r ipb[1] ipb[2] ipb[3] ipb[4] <<< "$1"

    local -r list_msb='0 128 192 224 240 248 252 254'

    for i in {1,2,3,4}; do
        if [[ $rest_to_zero ]]; then
            [[ ${ipb[i]} -eq 0 ]] || return 1
        else
            if [[ $list_msb =~ (^|[[:space:]])${ipb[i]}($|[[:space:]]) ]]; then
                local -r rest_to_zero=1
            elif [[ ${ipb[i]} -eq 255 ]]; then
                continue
            else
                return 1
            fi
        fi
    done

    return 0
}

########################################
# 描述: 测试IPv4 CIDR网络掩码是否有效
# 参数: $1:掩码
# 返回: 1: 无效；
#       0: 有效
# 实例: Is_IPv4_Cidr <mask>
########################################
function Is_IPv4_Cidr() {
    local -r regex='^[[:digit:]]{1,2}$'

    [[ $1 =~ $regex ]] || return 1
    [ "$1" -gt 32 ] || [ "$1" -lt 0 ] && return 1

    return 0
}


########################################
# 描述: 测试IPv4子网是否有效
# 参数: $1:测试的子网
# 返回: 1: 无效；
#       0: 有效
# 实例: Is_IPv4_Subnet <subnet>
########################################
function Is_IPv4_Subnet() {
    IFS='/' read -r tip tmask <<< "$1"

    is_ipv4_cidr "$tmask" || return 1
    is_ipv4 "$tip" || return 1

    return 0
}


########################################
# 描述: 计算IPv4子网的网络地址
# 参数: $1:IPv4地址，$2:IPv4网络掩码
# 返回: 网络地址
# 实例: get_ipv4_network <addr> <mask>
########################################
function get_ipv4_network() {
    is_ipv4 "$1" || return 1
    is_ipv4_netmask "$2" || return 1

    IFS='.' read -r ipb1 ipb2 ipb3 ipb4 <<< "$1"
    IFS='.' read -r mb1 mb2 mb3 mb4 <<< "$2"

    echo "$((ipb1 & mb1)).$((ipb2 & mb2)).$((ipb3 & mb3)).$((ipb4 & mb4))"
}


########################################
# 描述: 计算IPv4子网的广播地址
# 参数: $1:IPv4地址,$2:IPv4网络掩码
# 返回: 广播地址
# 实例: get_ipv4_broadcast <addr> <mask>
########################################
function get_ipv4_broadcast() {
    is_ipv4 "$1" || return 1
    is_ipv4_netmask "$2" || return 1

    IFS='.' read -r ipb1 ipb2 ipb3 ipb4 <<< "$1"
    IFS='.' read -r mb1 mb2 mb3 mb4 <<< "$2"

    nmb1=$((mb1 ^ 255))
    nmb2=$((mb2 ^ 255))
    nmb3=$((mb3 ^ 255))
    nmb4=$((mb4 ^ 255))

    echo "$((ipb1 | nmb1)).$((ipb2 | nmb2)).$((ipb3 | nmb3)).$((ipb4 | nmb4))"
}


########################################
# 描述: 将IPv4十进制网络掩码表示法转换为CIDR
# 参数: $1:要转换的十进制网络掩码
# 返回: 给定的十进制网络掩码的CIDR表示法
# 实例: mask2cidr <mask>
########################################
function mask2cidr() {
    is_ipv4_netmask "$1" || return 1

    local x=${1##*255.}
    set -- 0^^^128^192^224^240^248^252^254^ $(( (${#1} - ${#x})*2 )) "${x%%.*}"
    x=${1%%$3*}
    echo $(( $2 + (${#x}/4) ))
}


########################################
# 描述: 将CIDR表示法转换为IPv4十进制网络掩码
# 参数: $1:网络掩码
# 返回: 给定CIDR的十进制表示法
# 实例: cidr2mask <cidr>
########################################
function cidr2mask() {
    is_ipv4_cidr "$1" || return 1

    local i mask=""
    local full_octets=$(($1/8))
    local partial_octet=$(($1%8))

    for ((i=0;i<4;i+=1)); do
        if [ $i -lt $full_octets ]; then
            mask+=255
        elif [ $i -eq $full_octets ]; then
            mask+=$((256 - 2**(8-partial_octet)))
        else
            mask+=0
        fi

        test $i -lt 3 && mask+=.
    done

    echo $mask
}









































__network_init__


